from flask import Flask, render_template, request, jsonify, send_from_directory,Response,send_file,make_response, session, redirect, url_for
from datetime import datetime
from dp_core import FortuneGenerator
from ganzhi import DayFortune
import wuyun_liuqi
import configparser
import os
import sys
import json
import pandas as pd
import csv
import weekyun
import openpyxl
from openpyxl.utils.dataframe import dataframe_to_rows
from datetime import timedelta
import zipfile
import io
import re
from PIL import Image
import platform
from functools import wraps
if platform.system().lower()=='windows':
    this_system='windows'
elif platform.system().lower()=='darwin':
    this_system='apple'
elif platform.system().lower()=='linux':
    this_system='linux'
else:
    this_system='windows'


# Read config file
config = configparser.ConfigParser()
config.read('config.cfg',encoding='utf-8')

app = Flask(__name__, static_folder=config['Flask']['static_folder'])
app.secret_key = config['Authentication']['secret_key']

# 登录检查装饰器
def login_required(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        if not session.get('logged_in'):
            return redirect(url_for('login'))
        return f(*args, **kwargs)
    return decorated_function

# 登录路由
@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        username = request.form.get('username')
        password = request.form.get('password')
        
        if (username == config['Authentication']['username'] and 
            password == config['Authentication']['password']):
            session['logged_in'] = True
            session['username'] = username  # 存储用户名
            return redirect(url_for('index'))
        else:
            return render_template('login.html', error='用户名或密码错误')
    
    return render_template('login.html')

# 登出路由
@app.route('/logout')
def logout():
    session.pop('logged_in', None)
    return redirect(url_for('login'))


###########编辑五运六气#############
@app.route('/edit_gz_constitutions',methods=['GET','POST'])
@login_required
def edit_gz_constitutions_page():
    return render_template('edit_gz_constitutions.html')


@app.route('/get_gz_table',methods=['GET','POST'])
def get_gz_table():
    
    data=request.json
    gz=data['ganzhi']
    print(f'正在获取 {gz} 的体质数据')
    with open(config['Files']['wuyun_liuqi_tizhi_json'],'r',encoding='utf-8') as f:
        cons=json.load(f)

    # print(f'{gz}体质数据：{cons[gz]}')
    
    return jsonify({'res':'ok','data':cons[gz]})

@app.route('/update_gz_table',methods=['POST'])
def update_gz_table():
    try:
        data = request.json
        ganzhi = data['ganzhi']
        new_data = data['data']
        
        print(f'正在更新 {ganzhi} 的体质数据')
        
        # 读取现有的体质配置数据
        with open(config['Files']['wuyun_liuqi_tizhi_json'], 'r', encoding='utf-8') as f:
            cons = json.load(f)
        
        # 更新指定干支的数据
        cons[ganzhi] = new_data
        
        # 保存更新后的数据
        with open(config['Files']['wuyun_liuqi_tizhi_json'], 'w', encoding='utf-8') as f:
            json.dump(cons, f, ensure_ascii=False, indent=2)
        
        print(f'{ganzhi} 体质数据更新成功')
        return jsonify({'res': 'ok', 'msg': '数据保存成功'})
        
    except Exception as e:
        print(f'更新体质数据时出错: {str(e)}')
        return jsonify({'res': 'failed', 'msg': f'保存失败: {str(e)}'})



#######查看五运六气#########
@app.route('/wuyun_liuqi',methods=['GET','POST'])
def wuyun_liuqi_page():
    return render_template('wuyun_liuqi.html')


@app.route('/get_wylq_advice',methods=['GET','POST'])
def get_wylq_advice():
    data=request.json
    date_str=str(data['date'])
    try:
        res=wuyun_liuqi.wuYunLiuQi().get_wuyun_liuqi_advice(year=date_str)
        birth_res=wuyun_liuqi.wuYunLiuQi().get_tizhi(year=date_str)
        
        return jsonify({'res':'ok','msg':'get wuyun_liuqi data successfully.','data':res,'birth_tizhi':birth_res})
    
    except Exception as e:
        return jsonify({'res':'failed','msg':str(e)})



#######生日幸运色########

# 创建static目录并移动colorMap.txt
if not os.path.exists('static'):
    os.makedirs('static')
if os.path.exists('colorMap.txt'):
    os.rename('colorMap.txt', 'static/colorMap.txt')

# 初始化生日幸运色生成器
bir_lucky_colors_generator=DayFortune(geju_txt_dir=r'D:\jacklocal工作目录2\ejj\素材\config')
@app.route('/get_lucky_color',methods=['GET','POST'])
def get_bir_lucky_colors():
    # 1. 获取并验证前端数据
    try:
        req_data = request.get_json()
        if not req_data:
            return jsonify({'error': 'No JSON data received'}), 400
            
        print('Received data:', req_data)
        
        # 2. 提取关键字段
        date_str = req_data.get('date')  # 格式应为YYYYMMDD
        is_time_accurate = req_data.get('is_time_accurate', False)
        
        if not date_str :
            return jsonify({'error': 'Invalid date format (require YYYYMMDD)'}), 400

    except Exception as e:
        return jsonify({'error': f'Bad request: {str(e)}'}), 400

    # 3. 调用业务逻辑
    try:
        print(f'Generating colors for date: {date_str}, time accurate: {is_time_accurate}')
        if is_time_accurate:
            # print('accurate time')
            date_str=date_str
        else:
            # print('not accurate time')
            date_str=date_str[:8]
        res = bir_lucky_colors_generator.get_birthday_fortune_color(
            date_str=date_str
        )
        
        
        print('birthday lucky color res:',res)
        
        # 4. 格式化响应数据
        response = jsonify({
            'status': 'success',
            'date': date_str,
            'is_time_accurate': is_time_accurate,
            'data': res
        })

        

        # return jsonify(response)
        # 添加关键响应头
        response.headers['Content-Type'] = 'application/json'
        response.headers['Access-Control-Allow-Origin'] = '*'
        return response

    except Exception as e:
        import traceback
        print("="*50)
        print("ERROR TRACEBACK:")
        traceback.print_exc()  # 打印完整堆栈
        print("="*50)
        return jsonify({'error': str(e), 'stack': traceback.format_exc()}), 500


# 初始化运势生成器
generator = FortuneGenerator()

@app.route('/read_temp_save',methods=['GET','POST'])
def read_temp_save():
    try:
        json_file = config['Directories']['temp_save_file']
        if not os.path.exists(json_file):
            return jsonify({'status': 'error', 'message': f'文件不存在: {json_file}'})
            
        temp_save_data = pd.read_json(json_file, lines=True)
        return jsonify({
            'status': 'success',
            'data': temp_save_data.to_dict(orient='records')
        })
    except Exception as e:
        return jsonify({
            'status': 'error',
            'message': str(e),
            'file_path': json_file
        })

@app.route('/delete_date_riyun_record', methods=['POST'])
def delete_date_riyun_record():
    data = request.json
    date = data['date']
    json_file = config['Directories']['temp_save_file']
    
    if os.path.isfile(json_file):
        df = pd.read_json(json_file, lines=True)
        if not df.empty and date in df[0].values:
            df = df[df[0] != date]
            df.to_json(json_file, orient="records", lines=True, force_ascii=False)
            return jsonify({'status': 'success', 'message': f'{date}记录已删除'})
        return jsonify({'status': 'success', 'message': f'未找到{date}的记录'})
    return jsonify({'status': 'error', 'message': '文件不存在'})

@app.route('/deal_temp_save',methods=['GET','POST'])
def deal_temp_save():
    data = request.json
    json_file = config['Directories']['temp_save_file']
    
    # 检查文件是否存在，如果不存在则创建
    file_exists = os.path.isfile(json_file)
    
    # 读取CSV文件为DataFrame
    if file_exists:
        df = pd.read_json(json_file,lines=True)
    else:
        df = pd.DataFrame()
    
    # 检查是否存在相同日期的记录
    date = data['date']
    if not df.empty and date in df[0].values:
        # 删除相同日期的记录
        df = df[df[0] != date]
    
    # 添加新记录
    new_row = pd.DataFrame([list(data.values())])
    df = pd.concat([df, new_row], ignore_index=True)
    
    # 保存CSV文件
    df.to_json(json_file, orient="records", lines=True, force_ascii=False)
    
    return jsonify({'status': 'success'})

@app.route('/deal_ai_data', methods=['GET','POST'])
def deal_ai_data():
    data=request.json

    # 如果有对应的csv暂存记录，则删除。
    date = data['date']
    json_file = config['Directories']['temp_save_file']
    if os.path.isfile(json_file):
        df = pd.read_json(json_file,lines=True)
        if not df.empty and date in df[0].values:
            df = df[df[0] != date]
            df.to_json(json_file, orient="records", lines=True, force_ascii=False)
            

    try:
        res_wx_ai_final_text={}
        res_wx_color={}
        res_wx_luck={}
        res_wx_ai_txt={}
        for wx in ['wood','fire','earth','metal','water']:
            res=generator.generate_fortune_ai(wx=data[wx]['name'],color=data[wx]['color'],luck=data[wx]['luck'],pre_text=data['pre_text'],prompt_input=data[wx]['text'])
            res_wx_ai_final_text[data[wx]['name']]=res['final_text']
            res_wx_color[data[wx]['name']]=res['color']
            res_wx_luck[data[wx]['name']]=res['luck']
            res_wx_ai_txt[data[wx]['name']]=res['ai_text']
        
        print('deal ai data',data)

        return jsonify({'final_text':res_wx_ai_final_text,'pre_text':data['pre_text'],'color':res_wx_color,'luck':res_wx_luck,'ai_text':res_wx_ai_txt})
    except Exception as e:
        return jsonify(str(e))

@app.route('/update_color_map', methods=['POST'])
def update_color_map():
    data = request.json
    color = data['color']
    code = data['code']
    
    # 更新colorMap.txt
    with open('static/colorMap.txt', 'a', encoding='utf-8') as f:
        f.write(f'\n{color}:{code}')
    
    return jsonify({'status': 'success'})

from dp_core import ImageGenerator

# 初始化图片生成器
image_generator = ImageGenerator()

@app.route('/generate_images', methods=['POST'])
def generate_images():
    data = request.json
    fortune_text = data['text']
    date_str = datetime.now().strftime('%Y%m%d')
    
    try:
        # 生成图片
        image_paths = image_generator.generate_images(date_str, fortune_text)
        
        # 转换路径为web可访问路径
        web_paths = {}
        for element, path in image_paths.items():
            web_paths[element] = f'/temp_images/{date_str}/{os.path.basename(path)}'
            
        return jsonify({
            'status': 'success',
            'images': web_paths
        })
    except Exception as e:
        return jsonify({
            'status': 'error',
            'message': str(e)
        }), 500

@app.route('/get_wx_summary', methods=['GET', 'POST'])
def get_wx_summary():
    data=request.json
    # 获取当前日期
    # today = datetime.now().strftime('%Y%m%d') + '0808'
    today=data['date']+'0808'
    
    # 获取每日运势
    day_fortune = DayFortune(geju_txt_dir=os.path.join(config['Directories']['ganzhi_work_dir'],'素材','config'))
    result = day_fortune.get_daily_fortune_by_date(today)
    print(f'day_fortune.get_daily_fortune_by_date(today) result:\n{result}')

    # 处理五行十神格局
    if 'date_rels' in result:
        wuxing_map = {'木': '', '火': '', '土': '', '金': '', '水': ''}
        for wx in wuxing_map.keys():
            wuxing_shishen_txt = result['date_rels']['五行权重及格局'].get(wx,[])
            wuxing_map[wx] = wuxing_shishen_txt
        
        tg_notice=', '.join(word for sublist in result['date_rels']['天干关系'] for word in sublist)
        dz_notice=', '.join(word for sublist in result['date_rels']['地支关系'] for word in sublist)
        # 只有当两者都不为空时才用 " | " 连接，否则取不为空的项
        notice = ' | '.join(filter(None, [tg_notice, dz_notice]))

        # 将每个五行的十神用逗号连接
        wx_summary = {}
        for wx in wuxing_map.keys():
            wx_summary[wx] = ','.join(wuxing_map[wx])
        print('wx summary:',wx_summary) 
        return jsonify({'wx_summary': wx_summary,
                        'tg_dz_notice':notice,
                        'wx_text_prompt':result['date_rels']['五行权重及格局关键词'],
                        'date_info':datetime.strptime(result['date'],'%Y%m%d%H%M').strftime('%Y-%m-%d'),
                        'date_gz':result['date_rels']['日期干支'][0]+result['date_rels']['日期干支'][1]+'年'+ 
                                result['date_rels']['日期干支'][2]+result['date_rels']['日期干支'][3]+'月'+
                                result['date_rels']['日期干支'][4]+result['date_rels']['日期干支'][5]+'日'})
    return jsonify({'wx_summary': {}})

@app.route('/temp_images/<date>/<filename>')
def serve_temp_images(date, filename):
    temp_dir = os.path.join(config['Flask']['temp_images_dir'], date)
    return send_from_directory(temp_dir, filename)

@app.route('/static/<path:filename>')
def serve_static(filename):
    return app.send_static_file(filename)

@app.route('/generate_riyun', methods=['GET', 'POST'])
@login_required
def generate_riyun_page():
    return render_template('generate_riyun.html')

@app.route('/suibi', methods=['GET', 'POST'])
@login_required
def suibi_page():
    return render_template('suibi.html')


@app.route('/', methods=['GET', 'POST'])
@login_required
def index():
    return render_template('index.html')


@app.route('/riyun_input', methods=['GET', 'POST'])
@login_required
def riyun_input():
    # 获取当前日期
    today = datetime.now().strftime('%Y-%m-%d')
    
    # 初始化DayFortune
    day_fortune = DayFortune()

    # 处理表单提交
    if request.method == 'POST':
        selected_date = request.form.get('date')
        try:
            # 将日期转换为8位文本格式
            date_obj = datetime.strptime(selected_date, '%Y-%m-%d')
            date_str = date_obj.strftime('%Y%m%d')
            # 添加'0808'形成12位文本
            full_date_str = date_str + '0808'
            # 获取每日运势
            result = day_fortune.get_daily_fortune_by_date(full_date_str)
            # 处理五行十神格局
            if 'date_rels' in result:
                wuxing_map = {'木': '', '火': '', '土': '', '金': '', '水': ''}
                for wx in wuxing_map.keys():
                    wuxing_shishen_txt= result['date_rels']['五行权重及格局'].get(wx,[])
                    wuxing_map[wx]=wuxing_shishen_txt

                # 将每个五行的十神用逗号连接
                result['wx_summary']={}
                for wx in wuxing_map.keys():
                    result['wx_summary'][f'{wx}'] = ','.join(wuxing_map[wx])
        except ValueError:
            # 如果日期格式错误，使用今天日期
            today_str = datetime.now().strftime('%Y%m%d') + '0808'
            result = day_fortune.get_daily_fortune_by_date(today_str)
        
        return render_template('riyun_input.html', 
                            fortune=result, 
                            today=today)
    
    # GET请求时返回空结果
    return render_template('riyun_input.html', 
                         fortune="", 
                         images={},
                         today=today)

@app.route('/write_into_riyun_xlsx', methods=['GET', 'POST'])
def write_into_riyun_xlsx():
    print('writing into riyun xlsx')
    data=request.json
    print('write into xlsx data:',data)

    # 从配置文件中读取
    # riyun_fn = config['Files']['yunshi']

    # 从页面中接收
    riyun_fn = os.path.join(config['Directories']['ganzhi_work_dir'],'运势',data['xlsx_name'])
    # riyun_fn = os.path.join(config['Directories']['ganzhi_work_dir'],'运势','运势3.xlsx')
    # riyun_fn = os.path.join(config['Directories']['work_dir'],'运势','运势2.xlsx')
    # y,m,d=data['date'].split('-')
    # gz=ganzhi.GanZhi().cal_dateGZ(int(y),int(m),int(d),8)
    # data['tg']=gz['bazi'][4]
    # data['dz']=gz['bazi'][5]
    ### 旧的版本，有吉凶判断
    # _data=[data['date'],data['weekday'],data['date_gz'][0],data['date_gz'][1],data['pre_text'],
    #         data['wx_contents']['木']['color'],data['wx_contents']['木']['luck']+data['wx_contents']['木']['fortune_text'],
    #         data['wx_contents']['火']['color'],data['wx_contents']['木']['luck']+data['wx_contents']['火']['fortune_text'],
    #         data['wx_contents']['土']['color'],data['wx_contents']['木']['luck']+data['wx_contents']['土']['fortune_text'],
    #         data['wx_contents']['金']['color'],data['wx_contents']['木']['luck']+data['wx_contents']['金']['fortune_text'],
    #         data['wx_contents']['水']['color'],data['wx_contents']['木']['luck']+data['wx_contents']['水']['fortune_text']
    #         ]

    ### 新版本，仅有关键词
    _data=[data['date'],data['weekday'],data['date_gz'][0],data['date_gz'][1],data['pre_text'],
            data['wx_contents']['木']['color'],"【关键词】"+data['wx_contents']['木']['fortune_text'],
            data['wx_contents']['火']['color'],"【关键词】"+data['wx_contents']['火']['fortune_text'],
            data['wx_contents']['土']['color'],"【关键词】"+data['wx_contents']['土']['fortune_text'],
            data['wx_contents']['金']['color'],"【关键词】"+data['wx_contents']['金']['fortune_text'],
            data['wx_contents']['水']['color'],"【关键词】"+data['wx_contents']['水']['fortune_text']
            ]


    # print('_data:',_data)
    columns=['date', 'weekday', 'tg', 'dz', 'daoyu','color-mu', 'txt-mu', 'color-huo', 'txt-huo', 'color-tu', 'txt-tu', 'color-jin', 'txt-jin', 'color-shui', 'txt-shui']
        

    try:
        df=pd.DataFrame([_data],columns=columns)

        
        # print(df)
        ########
        # app=xw.App(visible=False)
        # wb=app.books.open(riyun_fn)
        # sheet=wb.sheets['运势']
        # last_row=sheet.range('A1048576').end('up').row
        
        # last_date=sheet.range(f'A{last_row}').value

        # date_input=datetime.strptime(data['date']+' 00:00:00','%Y-%m-%d %H:%M:%S')

        # # print(date_input)
        # # print(last_date)

        # dates=sheet.range(f'A3:A{last_row}').value
        # try:
        #     row_number=dates.index(date_input)+3
        # except:
        #     row_number=last_row+1
        # finally:            
        #     print(f'write into row {row_number}')
            
        #     # 将 DataFrame 数据写入 Excel 工作表的指定行号
        #     print(df.values.tolist)
        #     sheet.range(f'A{row_number}:N{row_number}').value=df.values

        #     wb.save(riyun_fn)
        #     wb.close()
        #     app.quit()
    
    #######

    # 打开 Excel 文件
        wb = openpyxl.load_workbook(riyun_fn)

        # 选择工作表
        sheet = wb['运势']

        # 获取最后一行的行号
        last_row = sheet.max_row

        # 获取最后一个日期
        last_date = sheet[f'A{last_row}'].value

        # 解析输入的日期
        date_input = datetime.strptime(data['date'] + ' 00:00:00', '%Y-%m-%d %H:%M:%S')

        # 查找日期在表中的位置
        dates = [sheet[f'A{i}'].value for i in range(3, last_row+1)]
        try:
            row_number = dates.index(date_input) + 3
        except ValueError:
            row_number = last_row + 1
        finally:
            print(f'write into row {row_number}')

            # 将 DataFrame 数据写入 Excel 工作表的指定行号
            for r_idx, row in enumerate(dataframe_to_rows(df, index=False,header=False), row_number):
                for c_idx, value in enumerate(row, 1):
                    sheet.cell(row=r_idx, column=c_idx, value=value)

            # 保存并关闭工作簿
            wb.save(riyun_fn)
            wb.close()
            return jsonify({'res':'ok'})

    except Exception as e:
        print('write xlsx error',e)
        return jsonify({'res':'failed','error':'write xlsx error'})

    

    return jsonify({'success':data})

def run_suibi(date_input='20240717',sb_xlsx='D:\\坚果云\\运势\\运势2.xlsx',output_dir='e:\\temp\\ejj\\日穿搭'):
        try:
            work_dir=config['Directories']['work_dir']
            p=weekyun.suiBiVideo(work_dir=work_dir,output_dir=output_dir)
            p.export_video(date_input=date_input,sb_xlsx=sb_xlsx)
            return {'res':'ok'}
        except Exception as e:
            return {'res':'failed','error':'sujiBiVideo.export_video()执行错误'}
        


@app.route('/generate_suibi',methods=['GET','POST'])
def generate_suibi():
        data=request.json
        date_input=data['dateInput']
        # format_date=f'{date_input[:4]}-{date_input[4:6]}-{date_input[6:]}'
        format_date=''.join(date_input.split('-'))
        fn=data['xlsx']
        
        xlsx=os.path.join(config['Directories']['work_dir'],'运势',fn)
        print('generate_suibi():',date_input,xlsx,format_date)
        output_dir=os.path.join(config['Directories']['output_dir'],'日穿搭')
        try:
            res_generate=run_suibi(date_input=format_date,sb_xlsx=xlsx,output_dir=output_dir)
       
            if res_generate['res']!='ok':
                return jsonify({'res':'failed','error':'run suibi() error'})
            
            else:
                return jsonify({'res':'ok','data':f'{date_input} 随笔视频生成OK'})

            
            # return zip
        except Exception as e:
            print('riyun() Error:',e)
            return jsonify({'res':'failed','error':e})

@app.route('/check_riyun_files',methods=['GET','POST'])
def check_riyun_files():
        data=request.json
        file_types=data['file_types']
        start_date=data['start_date']
        end_date=data['end_date']

        output_dir=config['Directories']['output_dir']

        datelist=[]
        stime,etime=datetime.strptime(start_date,'%Y-%m-%d'),datetime.strptime(end_date,'%Y-%m-%d')
        while stime<=etime:
            datelist.append(stime.strftime('%Y%m%d'))
            stime+=timedelta(days=1)

        res_dates=[]          
        miss_files={}  
        valid_dates=[]
        temp_mp3_files={}
        try:
            print('check riyun files...')
            for date_str in datelist:     
                miss_files[date_str]=[] 
                dir_name=f'{date_str[:4]}-{date_str[4:6]}-{date_str[6:]}'      
                if file_types=='img_txt':
                    check_file_names = ['1-木.jpg', '2-火.jpg', '3-土.jpg', '4-金.jpg', '5-水.jpg', f'{dir_name}_日运.txt',  f'{dir_name}-抖音封面.jpg',  f'{dir_name}-抖音内容.jpg']
                else:
                    check_file_names = ['1-木.jpg', '2-火.jpg', '3-土.jpg', '4-金.jpg', '5-水.jpg', f'{dir_name}_日运.txt',  f'{dir_name}-抖音封面.jpg',  f'{dir_name}-抖音内容.jpg',f'{date_str}-output_video.mp4']
                        
                pic_dir=os.path.join(output_dir,'日穿搭',dir_name)

                

                if os.path.isdir(pic_dir):
                    valid_dates.append(date_str)
                    directory_files = set(os.listdir(pic_dir))
                    miss_files[date_str]=[fn for fn in check_file_names if fn not in directory_files]
                    temp_mp3_files[date_str]=''

                    for fn in os.listdir(pic_dir):
                        if file_types=='img_txt_video' and fn.split('.')[-1].lower()=='mp3':
                            temp_mp3_files[date_str]='processing'


            for date_str in valid_dates:
                print(miss_files[date_str],temp_mp3_files[date_str])
                if len(miss_files[date_str])<=0 and temp_mp3_files[date_str]!='processing':
                    if date_str not in res_dates:
                            res_dates.append(date_str)


            print('miss files: ',miss_files)
            if res_dates:                
                return jsonify({'res':'ok','data':res_dates})
            else:
                return jsonify({'res':'failed','error':'no data'})
        except Exception as e:
            print('error: ',e)
            if res_dates:
                return jsonify({'res':'ok','data':res_dates})
            else:
                return jsonify({'res':'failed','error':f'Exception occurred: {str(e)}'})

def run_week_txt_cover(fn_num='1',prd=['20220822','20220828'],sense_word_judge='yes',desc_txt_show='yes',file_types='img_txt'):
    import weekyun
    work_dir=config['Directories']['ganzhi_work_dir']
    output_dir=config['Directories']['output_dir']
    if fn_num=='1':
        xls=os.path.join(work_dir,'运势','运势.xlsx')
    else:
        xls=os.path.join(work_dir,'运势','运势2.xlsx')

    try:

        eachday_output_dir=os.path.join(output_dir,'日穿搭')
        cover_save_dir=os.path.join(output_dir,'日穿搭','0-每周运势封图')

        print('\n正在处理每日穿搭配色图\n')
        print('work dir:',work_dir)
        week_pic=weekyun.ExportImage(work_dir=work_dir)            
        dec_txt=week_pic.batch_deal(prd=prd,out_put_dir=eachday_output_dir,xls=xls)        
            
    
        if dec_txt['res']=='ok':
            # print('\n正在处理每日穿搭配色图\n')
            # week_pic=week_yun.ExportImage(work_dir=work_dir)

            print('\n正在处理每日穿搭配色文案..\n')
            week_txts=weekyun.ExportWeekYunTxt(work_dir=work_dir,import_dec_dic=dec_txt)
            
            all_txt=week_txts.all_date_wx(prd=prd,xls=xls,save='yes',save_dir=eachday_output_dir,sense_word_judge=sense_word_judge,desc_txt_show=desc_txt_show)
            

            if file_types=='img_txt_video':
                print('\n正在生成视频\n')
                videos=weekyun.videoClips(work_dir=work_dir,import_dec_dic=dec_txt,import_txt=all_txt)
                videos.batch_export_video(prd=prd,xls=xls,save='no',save_dir=eachday_output_dir,sense_word_judge='no')


            return {'res':'ok'}
        else:
            return {'res':'failed','error':dec_txt['error']}
    except Exception as e:
        # raise FERROR('error where generate riyun pics and txt')
        print(e)
        return {'res':'failed','error':'error when generate riyun pics and txt：'+str(e)}   


@app.route('/generate_riyun_file', methods=['GET', 'POST'])
def generate_riyun_file():    
    data=request.json
    print('generate riyun() input data:',data)
    fn_num=data['fn_num']
    start_date=data['start_date']
    end_date=data['end_date']
    file_types=data['file_types']
    start_date_input=start_date.replace('-','')
    end_date_input=end_date.replace('-','')
    try:
        #desc_txt_show参数为是否需要饰品文字及音频
        res_generate=run_week_txt_cover(fn_num=fn_num,prd=[start_date_input,end_date_input],desc_txt_show='no',file_types=file_types)  
        # res_generate=run_week_txt_img_video(prd=[s,e],work_dir='D:\\工作目录\\ejj',xls=xls,output_dir='e:\\temp\\ejj',sense_word_judge='yes')
        # self.zip_and_download(prd=[start_date,end_date])  
        # print(res_generate)
        if res_generate['res']!='ok':
            return jsonify({'res':'failed','error':res_generate['error']})
        

        #将日期写入临时文件

        tmp_dir=tmp_fn=os.path.join(config['Directories']['output_dir'],'日穿搭','zip')
        if not os.path.exists(tmp_dir):
            os.makedirs(tmp_dir)
        tmp_fn=os.path.join(tmp_dir,'riyun_tmp')
        with open (tmp_fn, 'w') as f:
            f.write(f'{start_date},{end_date}')

        return jsonify({'res':'ok','res_data':f'{start_date},{end_date},OK'})

        
        # return zip
    except Exception as e:            
        print('generate_riyun() Error:',e)
        return jsonify({'res':'failed','error':e})
    
@app.route('/write_into_suibi_xlsx', methods=['GET', 'POST'])    
def write_into_suibi_xlsx():
    print('writing into suibi xlsx')
    data=request.json
    date=data['date_input']
    xlsx=data['xlsx']
    suibi_text=data['suibi_text']

    # 从配置文件中读取
    # suibi_fn = config['Files']['yunshi']

    # 从页面中接收
    suibi_fn = os.path.join(config['Directories']['work_dir'],'运势',xlsx)
    suibi_fn = os.path.join(config['Directories']['work_dir'],'运势','运势2.xlsx')
    # y,m,d=data['date'].split('-')
    # gz=ganzhi.GanZhi().cal_dateGZ(int(y),int(m),int(d),8)
    # data['tg']=gz['bazi'][4]
    # data['dz']=gz['bazi'][5]
    _data=[date,suibi_text]

    # print('_data:',_data)
    columns=['date', 'suibi_text']
        
    try:
        df=pd.DataFrame([_data],columns=columns)

        print(df)
        
        # print(df)
        ########
        # app=xw.App(visible=False)
        # wb=app.books.open(suibi_fn)
        # sheet=wb.sheets['运势']
        # last_row=sheet.range('A1048576').end('up').row
        
        # last_date=sheet.range(f'A{last_row}').value

        # date_input=datetime.strptime(data['date']+' 00:00:00','%Y-%m-%d %H:%M:%S')

        # # print(date_input)
        # # print(last_date)

        # dates=sheet.range(f'A3:A{last_row}').value
        # try:
        #     row_number=dates.index(date_input)+3
        # except:
        #     row_number=last_row+1
        # finally:            
        #     print(f'write into row {row_number}')
            
        #     # 将 DataFrame 数据写入 Excel 工作表的指定行号
        #     print(df.values.tolist)
        #     sheet.range(f'A{row_number}:N{row_number}').value=df.values

        #     wb.save(riyun_fn)
        #     wb.close()
        #     app.quit()
    
    #######

    # 打开 Excel 文件
        wb = openpyxl.load_workbook(suibi_fn)

        # 选择工作表
        sheet = wb['随笔']

        # 获取最后一行的行号
        last_row = sheet.max_row

        # 获取最后一个日期
        last_date = sheet[f'A{last_row}'].value

        # 解析输入的日期
        date_input = datetime.strptime(date + ' 00:00:00', '%Y-%m-%d %H:%M:%S')

        # 查找日期在表中的位置
        dates = [sheet[f'A{i}'].value for i in range(2, last_row+1)]
        try:
            row_number = dates.index(date_input) + 2
        except ValueError:
            row_number = last_row + 1
        finally:
            print(f'write into subi xlsx in row {row_number}')

            # 将 DataFrame 数据写入 Excel 工作表的指定行号
            for r_idx, row in enumerate(dataframe_to_rows(df, index=False,header=False), row_number):
                for c_idx, value in enumerate(row, 1):
                    sheet.cell(row=r_idx, column=c_idx, value=value)

            # 保存并关闭工作簿
            wb.save(suibi_fn)
            wb.close()
            return jsonify({'res':'ok'})


    except Exception as e:
        print('write suibi xlsx error',e)
        return jsonify({'res':'failed','error':'write suibi xlsx error'})

    

    return jsonify({'success':data})

@app.route('/check_suibi_files', methods=['GET', 'POST'])    
def check_suibi_files():
        data=request.json
        start_date=data['start_date']
        date_str=''.join(start_date.split('-'))
        output_dir=config['Directories']['output_dir'] 

        res_dates=[] 
        valid_dates=[]
        temp_mp3_files={}
        try:
            print('check suibi files...')            
   
            dir_name=f'{date_str[:4]}-{date_str[4:6]}-{date_str[6:]}'      
            check_file_names =[f'{date_str}-suiBi_video.mp4']
                    
            pic_dir=os.path.join(output_dir,'日穿搭',dir_name)

            
            
            if os.path.isdir(pic_dir):                
                valid_dates.append(date_str)
                temp_mp3_files[date_str]=''
                for fn in os.listdir(pic_dir):
                    # print(fn,check_file_names,fn in check_file_names,res_dates,len(res_dates))
                    if fn in check_file_names:                        
                        res_dates.append(date_str)
                    if fn.split('.')[-1].lower()=='mp3':
                        temp_mp3_files[date_str]='processing'

            if len(res_dates)>0 and temp_mp3_files[date_str]!='processing':                
                return jsonify({'res':'ok','data':res_dates})
            else:
                return jsonify({'res':'failed','error':'no data'})
        except Exception as e:
            if len(res_dates)>0 and temp_mp3_files[date_str]!='processing':    
                return jsonify({'res':'ok','data':res_dates})
            else:
                return jsonify({'res':'failed','error':f'Exception occurred: {str(e)}'})

@app.route('/check_suibi_pic', methods=['GET', 'POST'])
def check_suibi_pic(date_input=None):
    if date_input is None:
        data=request.json
        date_input=data['dateInput']

    format_date=f'{date_input[:4]}{date_input[4:6]}{date_input[6:]}'
    work_dir=config['Directories']['work_dir']
    output_dir=config['Directories']['output_dir']
    pic_dir=os.path.join(output_dir,'日穿搭',date_input)
    pics=[]
    try:
        if os.path.exists(pic_dir):
            for fn in os.listdir(pic_dir):
                if re.match(r'\d{8}-s\d{2}.jpg',fn):
                    pics.append(fn)
                    max_num=int(fn.split('.')[0].split('-')[1][1:])
        else:
            return jsonify({'res':'failed','error':'无随笔图片文件夹'})
        
        if len(pics)==0:
            return jsonify({'res':'failed','error':'无随笔图片'})
    except Exception as e:
        return jsonify({'res':'failed','error':'获取随笔图片错误'+str(e)})
        
    return jsonify({'res':'ok','pic_list':pics,'max_num':max_num})

@app.route('/zip_and_download', methods=['GET', 'POST'])
def zip_and_download():
    # prd_input=request.data.decode('utf-8')
    date_input=request.args.get('date')
    if not date_input:
        tmp_fn=os.path.join(config['Directories']['output_dir'],'日穿搭','zip','riyun_tmp')
        with open (tmp_fn, 'r') as f:
            prd_input=f.read()
        
        # print(prd_input)
        # prd_input='2023-08-22,2023-08-22'
        prd=prd_input.split(',')
    else:
        date_str=f'{date_input[:4]}-{date_input[4:6]}-{date_input[6:]}'
        prd=[date_str,date_str]


    print('zip_and_download() ',prd)
    if prd[0]==prd[1]:
        output_filename=prd[0]
    else:
        output_filename=prd[0]+'-'+prd[1]

    path=os.path.join(config['Directories']['output_dir'],'日穿搭')
    memory_file = io.BytesIO()
    with zipfile.ZipFile(memory_file, 'w', zipfile.ZIP_STORED) as zipf:
        for root, dir, files in os.walk(path):
            for file in files:                    
                try:     
                    if this_system=='windows':
                        dir_date_name=root.split('\\')[-1]
                    elif this_system=='apple' or this_system=='linux':
                        dir_date_name=root.split('/')[-1]
                    if datetime.strptime(prd[0],'%Y-%m-%d')<=datetime.strptime(dir_date_name,'%Y-%m-%d')<=datetime.strptime(prd[1],'%Y-%m-%d'):
                        if 'suiBi_video' not in file:
                            file_path = os.path.join(root, file)
                            arcname = os.path.relpath(file_path, path)
                            zipf.write(file_path,arcname)
        
                except Exception as e:
                    print('zip and download error:',e)
                    pass

    memory_file.seek(0)

    return Response(memory_file.getvalue(),
                    mimetype='application/zip',
                    headers={'Content-Disposition': f'attachment;filename={output_filename}.zip'})

@app.route('/zip_and_download_suibi', methods=['GET', 'POST'])
def zip_and_download_suibi():
    date_input=request.args.get('dateInput').split('.')[0]
    print('suibi zip and download:',date_input)
    # format_date=datetime.strftime(date_input,'%Y%m%d')
    format_date=''.join(date_input.split('-'))

    path=os.path.join(config['Directories']['output_dir'],'日穿搭')

    video_dir=os.path.join(path,f'{format_date[:4]}-{format_date[4:6]}-{format_date[6:]}')

    for fn in os.listdir(video_dir):
        if 'suiBi_video' in fn:
            output_filename=os.path.join(video_dir,f'{format_date}-suiBi_video.mp4')

    try:
        return send_file(output_filename,
                        mimetype='video/mp4',
                        as_attachment=True)
    except Exception as e:
        print(f"Error serving file: {e}")
        return Response(f"Error serving file: {e}", status=500)

    # return Response(memory_file.getvalue(),
    #                 mimetype='application/zip',
    #                 headers={'Content-Disposition': f'attachment;filename={output_filename}.zip'})

def allowed_file_suibi(filename):
    return "." in filename and filename.rsplit(".", 1)[1].lower() in {"jpg","jpeg","png"}


@app.route('/upload_pic_suibi', methods=['GET', 'POST'])
def upload_pic_suibi():
    fn_date=datetime.now().strftime('%Y-%m-%d')
    
    file = request.files["file"]
    filename =  request.args.get("filename")
    id_input=request.args.get('id')
    date_input=request.args.get('date_input')

    pics_data=check_suibi_pic(date_input=date_input)
    pics=pics_data.get_json()

    print('pics:',pics)

    if not "image/" in  file.content_type or not filename.endswith((".jpg", ".jpeg", ".png")):
        return {"message": "没有选择文件 image"}, 400
    
    # file = request.files["image"]
    if file.filename == "":
        return {"message": "没有选择文件 empty"}, 400

    # if file.content_type.split('/')[0] != 'image':
    # # 文件不是图片类型，返回错误信息
    #     return {"message": "请上传图片文件"},400
    
    if file and allowed_file_suibi(filename):
        # filename = secure_filename(filename)
        if pics['res']=='ok':
            pic_num=str(int(pics['max_num'])+1).zfill(2)
        else:
            pic_num='01'
        new_fn=f"{''.join(date_input.split('-'))}-s{pic_num}.jpg"
        print('checked filename:',filename)
        output_dir=config['Directories']['output_dir']    
        pic_dir=os.path.join(output_dir,'日穿搭',date_input)
        if not os.path.exists(pic_dir):
            os.makedirs(pic_dir)
        save_fn=os.path.join(pic_dir, new_fn)       
        file.save(save_fn)
        img = Image.open(save_fn)
        img=img.convert('RGB')
        quality=95
        resize_img=img.resize((720,960))
        img.save(save_fn, quality=quality)
        # target_size_kb=1300
        # step=10
        # while True:
        #     img.save(save_fn, quality=quality)
        #     #压缩图片                
        #     file_size_kb = os.path.getsize(save_fn) / 1024            
        #     if file_size_kb <= target_size_kb or quality == 0:
        #         break
        #     quality -= step
        #     if quality < 0:
        #         quality = 0
        pics_data=check_suibi_pic(date_input=date_input)
        pics=pics_data.get_json()

        return {"message": "上传成功","max_num":pics['max_num']},200
    else:
        return {"message": "只能上传图片"}, 400


def serve_single_file(output_filename):
    try:
        return send_file(output_filename,
                        mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
                        as_attachment=True)
    except Exception as e:
        print(f"Error serving file: {e}")
        return Response(f"Error serving file: {e}", status=500)


if __name__ == '__main__':
    # app.run(host='0.0.0.0', debug=True)
    print('sys.argv:',sys.argv)
    if len(sys.argv)>1:
        print(f'服务器为：{sys.argv[1]}:5025')
        app.run(debug=True,host=sys.argv[1],port=5025)
    else:
        app.run(debug=True)
